﻿using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml.Linq;
using System.Xml.Serialization;
using ZeroBug.EasyFlow.Communication;
using ZeroBug.EasyFlow.Core;

namespace Kimd.TcpIpComm
{
    public class TCPClient : ICommunicationClient
    {
        public event EventHandler<DataReceivedEventArgs<byte[]>>? OnDatagramReceived;
        public event EventHandler<CommErrorEventArgs>? OnErr;

        public bool? Connect(CommunicationConfig config, ICommClientState state)
        {
            try
            {
                if (state.IsConnected == true)
                    Disconnect(state);
                (state as TCPClientCommState)!.TcpClient = new TcpClient();
                (state as TCPClientCommState)!.TcpClient.Connect(IPAddress.Parse((config as TCPClientConfig)!.IpAddress), (config as TCPClientConfig)!.Port);
                if (state.IsConnected == true)
                {

                    (state as TCPClientCommState)!.Buffer = new byte[(state as TCPClientCommState)!.TcpClient.ReceiveBufferSize];
                    (state as TCPClientCommState)!.NetworkStream.BeginRead((state as TCPClientCommState)!.Buffer, 0, (state as TCPClientCommState)!.Buffer.Count(), new AsyncCallback(HandleTcpServerReceive), state);
                }
            }
            catch (Exception ex)
            {
                OnErr?.Invoke(this, new CommErrorEventArgs("连接失败", ex));
            }
            return state.IsConnected;
        }

        public bool Disconnect(ICommClientState state)
        {
            bool result = false;
            try
            {
                if ((state as TCPClientCommState)!.TcpClient != null)
                {
                    if ((state as TCPClientCommState)!.IsConnected == true)
                        (state as TCPClientCommState)!.TcpClient.Close();
                    (state as TCPClientCommState)!.TcpClient.Dispose();
                    result = true;
                }
            }
            catch(Exception ex)
            {
                OnErr?.Invoke(this, new CommErrorEventArgs("断开失败", ex));
            }
            return result;
        }

        public bool Send(ICommClientState state, byte[] data)
        {
            if (data == null)
                throw new ArgumentNullException("datagram");
            bool result = false;
            try
            {
                if (state.IsConnected == true)
                {
                    if ((state as TCPClientCommState)!.TcpClient != null)
                    {
                        result = ((state as TCPClientCommState)!.TcpClient.Client.Send(data) >= 0);
                    }
                }
            }
            catch (Exception ex)
            {
                OnErr?.Invoke(this, new CommErrorEventArgs("发送失败", ex));
            }
            return result;
        }

        public bool Send(ICommClientState state, string data, Encoding encoding)
        {
            if (data == null)
                throw new ArgumentNullException("datagram");
            bool result = false;
            try
            {
                if (state.IsConnected == true)
                {
                    if ((state as TCPClientCommState)!.TcpClient != null)
                    {
                        byte[] datas = encoding.GetBytes(data);
                        result = ((state as TCPClientCommState)!.TcpClient.Client.Send(datas) >= 0);
                    }
                }
            }
            catch (Exception ex)
            {
                OnErr?.Invoke(this, new CommErrorEventArgs("发送失败", ex));
            }
            return result;
        }

        private void HandleTcpServerReceive(IAsyncResult ar)
        {
            try
            {
                TCPClientCommState? socket_Client = ar.AsyncState as TCPClientCommState;
                int num = 0;
                try
                {
                    num = socket_Client!.NetworkStream.EndRead(ar);
                }
                catch (Exception ex)
                {
                    OnErr?.Invoke(this, new CommErrorEventArgs("接收异常", ex));
                }
                if (num == 0)
                {
                    OnErr?.Invoke(this, new CommErrorEventArgs("接收为空", null));
                    return;
                }
                byte[] receivedBytes = new byte[num];
                Buffer.BlockCopy(socket_Client!.Buffer, 0, receivedBytes, 0, num);
                socket_Client.NetworkStream.BeginRead(socket_Client.Buffer, 0, socket_Client.Buffer.Length, new AsyncCallback(HandleTcpServerReceive), socket_Client);
                OnDatagramReceived?.Invoke(this, new DataReceivedEventArgs<byte[]>(receivedBytes));
            }
            catch (Exception ex)
            {
                OnErr?.Invoke(this, new CommErrorEventArgs("接收异常", ex));
            }
        }
    }
}
